package com.practice.designMode.strategy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;


import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;


@RestController
public class CustomerController {

    /**
     * 用策略模式优化if-else逻辑
     * 一套方法论
     * 1.抽象逻辑——策略接口
     * 2.定义具体逻辑——具体策略
     * 3.处理流程简化——上下文
     * @param recharge
     * @return
     */
//    @GetMapping("/customer/{recharge}")
//    public String customer(@PathVariable(value = "recharge") int recharge){
//        if(recharge > 0 && recharge <= 100){
//            return "normal customer";
//        }
//        if(recharge > 100 && recharge <= 10000){
//            return "small customer";
//        }
//        if(recharge > 10000 && recharge <= 100000){
//            return "big customer";
//        }
//        if(recharge > 100000){
//            return "exclusive customer";
//        }
//        return "find not customer";
//    }

    private Map<UserType,CustomService> customServiceMap;

    @Autowired
    private DefaultCustomerService defaultCustomerService;

    @GetMapping("/customer/{recharge}")
    public String customer(@PathVariable(value = "recharge") int recharge){
        // 将用户类型判断逻辑封装到枚举类中
        UserType userType = UserType.typeOf(recharge);
        // 用map进行策略的存储，避免使用list进行搜索
        CustomService customService = customServiceMap.getOrDefault(userType,defaultCustomerService);
        return customService.findCustomService();
    }

    @Autowired
    public void setCustomServiceMap(List<CustomService> customServiceList){
        this.customServiceMap = customServiceList.stream()
                // 用注解的方式将策略条件和具体策略进行绑定
                .filter(customService -> customService.getClass().isAnnotationPresent(SupportUserType.class))
                //Function接口提供了一个静态方法identity()，它返回一个恒等函数。恒等函数的作用是将输入参数原样返回，即返回值与输入值相同。
                //用途：在流操作中，当你希望将流中的元素直接作为结果返回时，可以使用Function.identity()。
                .collect(Collectors.toMap(this::findUserTypeFromService, Function.identity()));
        if(this.customServiceMap.size() != UserType.values().length){
            throw new IllegalArgumentException("There is userType has not its handler");
        }
    }

    private UserType findUserTypeFromService(CustomService customService){
        SupportUserType supportUserType = customService.getClass().getAnnotation(SupportUserType.class);
        return supportUserType.value();
    }

}
